#include <json_object.h>
#include <json_util.h>
#include <curl.h>
#include <stdlib.h>
#include <string.h>
#define TEST

struct wordpress {
	char *url;
	char *password;
	char *user;
};

enum methodNumber {
	ERROR,
	GET_POST,
	PUBLISH_POST,
	GET_RECENT_POSTS,
	GET_CATEGORY_index,
};

// declare the extern functions.
extern struct json_object * wordpress_method_through_json(struct wordpress *blog,
		char const *method,
		struct json_object *data);
extern const char *get_url_blog(struct wordpress *blog);
#ifdef TEST
extern int test_json_parse(struct json_object *json);
#endif


// declare the static functions.
static size_t process_data(void *buffer, size_t size, size_t nmemb, void *usrer_p);
static struct json_object * wordpress_json_app_get_post(struct wordpress *blog, struct json_object *data);
static enum methodNumber getMethodNumber(const char *method);
static int get_file_from_server(const char *url, const char *filename);
static struct json_object * wordpress_json_app_get_recent_posts(
		struct wordpress *blog,
		struct json_object *data);
static struct json_object * wordpress_json_app_get_category_index(
		struct wordpress *blog,
		struct json_object *data);
static struct json_object * wordpress_json_app_publish_post(
		struct wordpress *blog,
		struct json_object *data);




// define extern functions.
extern const char *get_url_blog(struct wordpress *blog)
{
	if (!blog) {
		fprintf(stderr, "error: blog's address is null.\n");
		exit(1);
	}
	return blog->url;
}

#ifdef TEST
extern int test_json_parse(struct json_object *json)
{
	//struct json_object *body_json = json_object_from_file(filename);
	struct json_object *post = NULL;
	struct json_object *content = NULL;
	json_object_object_get_ex(json, "post", &post);
	json_object_object_get_ex(post, "content", &content);
	const char *content_string = json_object_get_string(content);
	printf("content:\n%s", content_string);
	return 1;
}
#endif


extern struct json_object * wordpress_method_throught_json(struct wordpress *blog,
		char const *method,
		struct json_object *data)
{
	struct json_object *ret = NULL;
	switch (getMethodNumber(method))
	{
		case ERROR:
			printf("do not have the method");
			exit(1);
		case GET_POST:
			//printf("I will do get_post method of wordpress.\n");
			return wordpress_json_app_get_post(blog, data);
		case PUBLISH_POST:
			return wordpress_json_app_publish_post(blog,data);
		case GET_RECENT_POSTS:
			return wordpress_json_app_get_recent_posts(blog, data);
	}
	return ret;
}








// define the static functions.
//

static struct json_object * wordpress_json_app_get_category_index(
		struct wordpress *blog,
		struct json_object *data)
{
	char url[256] = {0,};
	sprintf(url, "%s?json=get_category_index&json_unescaped_unicode=true",get_url_blog(blog));
	get_file_from_server(url, "category_index.json");
	return json_object_from_file("category_index.json");
}

static struct json_object * wordpress_json_app_publish_post(
		struct wordpress *blog,
		struct json_object *data)
{
	char url[256] = {0,};
	sprintf(url, "%s/wp-json/wp/v2/posts", blog->url);
	curl = curl_easy_init();
	if (curl) {
		curl_easy_setopt(curl, CURLOPT_URL, (char *)url);
		struct curl_slist *headers = NULL;

		//add HTTP Headers
		headers = curl_slist_append(headers, "Accept:application/json");
		headers = curl_slist_append(headers, "Content-Type:application/json");
		headers = curl_slist_append(headers, "Charset:utf-8");


		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
		curl_easy_setopt(curl, curlopt_postfileds, json_object_to_json_string(data));
	}

}

static struct json_object * wordpress_json_app_get_recent_posts(
		struct wordpress *blog,
		struct json_object *data)
{
	char url[256] = {0,};
	sprintf(url, "%s?json=get_recent_posts&json_unescaped_unicode=true", blog->url);
	get_file_from_server(url, "recent_posts.json");
	return json_object_from_file("recent_posts.json");
}

static int get_file_from_server(const char *url, const char *filename)
{
	FILE * fd = fopen(filename, "w+");
	int ret = 1;
	if ( fd == NULL) {
		fprintf(stderr, "error: can't create the file \"%s\".\n",
				filename);
		return 0;
	}
	CURL *easy_handle = curl_easy_init();
	if (easy_handle == NULL) {
		fprintf(stderr, "error: curl's initialiation is wrong!\n"); 
	}
	curl_easy_setopt(easy_handle, CURLOPT_URL, url);
	curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, process_data);
	curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, fd);
 	curl_easy_perform(easy_handle);
	fclose(fd);
	curl_easy_cleanup(easy_handle);
	curl_global_cleanup();
	return ret;
}

static enum methodNumber getMethodNumber(const char *method)
{
	if (strcmp(method, "get_post") == 0)
		return GET_POST;
	return ERROR;
}

static size_t process_data(void *buffer, size_t size, size_t nmemb, void *user_p)
{ 	FILE *fp = (FILE *)user_p;
	size_t return_size = fwrite(buffer, size, nmemb, fp);
	//cout << (char *)buffer << endl;
	//fprintf(fp, "%s", (char *)buffer);
	return return_size;
	//return 1;
}


static struct json_object *wordpress_json_app_get_post(struct wordpress *blog, struct json_object *data)
{
	// check the blog and data parameters.
	if ( blog == NULL || data == NULL) 
		exit(1);

	//parse out parameters for get_post of wordpress.
	//parse out post_id.
	struct json_object *post_id_json = NULL;
	json_object_object_get_ex(data, "post_id", &post_id_json);
	const char *post_id = json_object_get_string(post_id_json);

	char filename[256] = {0,};
	sprintf(filename, "%s.json", post_id);
 	// FILE *post_json = fopen(filename, "w+");
	char url[256] = {0,};
	sprintf(url, "%s?json=get_post&post_id=%s&json_unescaped_unicode=true", blog->url, post_id);
	// printf("%s\n", url);


 	// 获取easy handle
	// CURL *easy_handle = curl_easy_init();

	// add http header
	// struct curl_slist *headers=(struct curl_slist *)NULL;
	// headers = curl_slist_append(headers, "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
	// headers = curl_slist_append(headers, "Accept-Encoding: gzip, deflate");
	// headers = curl_slist_append(headers, "Accept-Language: en-US,en;q=0.5");
	// headers = curl_slist_append(headers, "Connection: keep-alive");
	// headers = curl_slist_append(headers, "Host: www.supermew.top");
	// headers = curl_slist_append(headers, "Upgrade-Insecure-Requests: 1");
	// headers = curl_slist_append(headers, "User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0");


	//FILE *fp_header = fopen("header.json", "w+");
	//curl_easy_setopt(easy_handle, CURLOPT_HTTPHEADER, headers);
	//curl_easy_setopt(easy_handle, CURLOPT_URL, url);
	//curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, process_data);
	//curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, post_json);
	//curl_easy_setopt(easy_handle, CURLOPT_HEADERDATA, fp_header);
	//curl_easy_setopt(easy_handle, CURLOPT_HEADERDATA, post_json);

 	//curl_easy_perform(easy_handle);
 	// 释放资源
	//fclose(fp_header);
	//fclose(post_json);
	//curl_easy_cleanup(easy_handle);
	//curl_global_cleanup();
	
	get_file_from_server(url, filename);
	return json_object_from_file(filename);
}


#ifdef TEST
int main(void)
{
	// struct blog.
	struct wordpress *blog = (struct wordpress *)malloc(
			sizeof(struct wordpress));
	blog->url = "http://www.supermew.top/";

	//struct the data for get_post method.
	struct json_object *data = json_object_new_object();
	struct json_object *post_id = json_object_new_string("1591");
	json_object_object_add(data, "post_id", post_id);

	//testing get_post.
	struct json_object *ret = wordpress_method_throught_json(blog, "get_post", data);

	//testing for parse the json .
	test_json_parse(ret);
 	return 0;

}
#endif
